package io.dy.main;

import io.dy.model.Order;
import org.junit.Test;

import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * @author : dmj
 * @date: 2024/12/18 5:16 下午
 * @description:
 */
public class Report {

    public static final List<Order> list = Arrays.asList(
            new Order("上海","dy","00001"),
            new Order("上海","sy","00002"),
            new Order("上海","zm","00003"),
            new Order("上海","fd","00004"),
            new Order("上海","dy","00005"),
            new Order("上海","dy","00006"),
            new Order("上海","sy","00007"),
            new Order("上海","fd","00008"),

            new Order("北京","wsy","00009"),
            new Order("北京","gz","00010"),
            new Order("北京","zx","00011"),
            new Order("北京","csl","00012"),
            new Order("北京","wsy","00013"),
            new Order("北京","wsy","00014"),
            new Order("北京","gz","00015"),
            new Order("北京","csl","00016"),

            new Order("广州","ss","00017"),
            new Order("广州","msq","00018"),
            new Order("广州","gzl","00019"),
            new Order("广州","wr","00020"),
            new Order("广州","wr","00021"),
            new Order("广州","wr","00022"),
            new Order("广州","msq","00023"),
            new Order("广州","ss","00024")
    );


    /**
     * 统计每个用户总共下了多少单
     */
    @Test
    public void need_01(){
        Map<String, Long> collect = list.stream().collect(Collectors.groupingBy(Order::getUserId, Collectors.counting()));
        for (Map.Entry<String, Long> entry : collect.entrySet()) {
            System.out.println(entry);
        }
    }

    /**
     * 统计每个地区下总共下了多少单
     */
    @Test
    public void need_02(){
        Map<String, Long> collect = list.stream().collect(Collectors.groupingBy(Order::getAreaName, Collectors.counting()));
        for (Map.Entry<String, Long> entry : collect.entrySet()) {
            System.out.println(entry);
        }
    }

    /**
     * 统计每个地区下具体每个用户下了多少单
     */
    @Test
    public void need_03(){
        Map<String, Map<String, Long>> collect = list.stream()
                .collect(Collectors.groupingBy(Order::getAreaName, Collectors.groupingBy(Order::getUserId, Collectors.counting())));
        for (Map.Entry<String, Map<String, Long>> entry : collect.entrySet()) {
            System.out.println(entry.getKey());
            for (Map.Entry<String, Long> innerEntry : entry.getValue().entrySet()) {
                System.out.println("\t" + innerEntry);
            }
            System.out.println("---------------------------");
        }
    }

    /**
     * 统计每个地区下单最多的用户且下了多少单
     * <地区, <用户, 下单数>>
     *     两次分组 求内部分组value最大值
     */
    @Test
    public void need_04(){
        /**
         *
         */
        Map<String, Map<String, Long>> collect = list.stream()
                .collect(Collectors.groupingBy(Order::getAreaName, Collectors.groupingBy(Order::getUserId, Collectors.counting())));

        Stream<Map.Entry<String, Map.Entry<String, Long>>> stream = collect.entrySet().stream()
                .map(entry -> new AbstractMap.SimpleEntry<>(
                        entry.getKey(),
                        entry.getValue().entrySet().stream().max(Map.Entry.comparingByValue()).orElse(null)
                ));

        Map<String, Map<String, Long>> collect1 = stream.collect(Collectors.toMap(
                Map.Entry::getKey,
                outerEntry -> {
                    Map.Entry<String, Long> innerEntry = outerEntry.getValue();
                    return Collections.singletonMap(innerEntry.getKey(), innerEntry.getValue()); // Inner Map
                },
                (existing, replacement) -> replacement
        ));

        System.out.println(collect1);
    }


    @Test
    public void need_05(){
        /**
         *
         */
        Map<String, Map<String, Long>> collect = list.stream()
                .collect(Collectors.groupingBy(Order::getAreaName, Collectors.groupingBy(Order::getUserId, Collectors.counting())));

        Stream<AbstractMap.SimpleEntry<String, List<Map.Entry<String, Long>>>> entryStream = collect.entrySet().stream()
                .map(entry -> new AbstractMap.SimpleEntry<>(
                        entry.getKey(),
                        entry.getValue().entrySet().stream().sorted(Map.Entry.<String,Long>comparingByValue().reversed()).limit(2).collect(Collectors.toList())
                ));

        Map<String, Map<String, Long>> collect1 = entryStream.collect(Collectors.toMap(
                Map.Entry::getKey,
                outerEntry -> {
                    List<Map.Entry<String, Long>> value = outerEntry.getValue();
                    Map<String, Long> map = new TreeMap<>();
                    value.forEach(entry -> map.put(entry.getKey(), entry.getValue()));
                    return map;
                },
                (o, n) -> n
        ));
        System.out.println(collect1);
    }

}
